﻿using SuperSocket.Channel;
using System;
using System.Threading.Tasks;

namespace SuperSocket.Client.HttpCode;

public sealed class HttpCode
{
    private static readonly HttpPackageEncoder _Encoder = new();

    public HttpCode(HttpProxyItem httpProxy)
    {
        Proxy = httpProxy;
    }

    /// <summary>
    /// 代理
    /// </summary>
    public HttpProxyItem Proxy { get; set; }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="TimeoutException"></exception>
    /// <exception cref="Exception"></exception>
    public async ValueTask<HttpRequest> SendAsync(HttpRequestItem request)
    {
        ArgumentNullException.ThrowIfNull(Proxy, nameof(Proxy));

        var connectState = await Proxy
            .CreataConnector(request.GetSslStreamConnector()) //获取socket连接器 http 或者 socket5
            .ConnectAsync(request.GetRemoteEndPoint()) //连接
            .AsTask() //将valueTask转换到task
            .TimeoutAfter(request.Timeout); //等待超时

        if (!connectState.Result)
            throw new Exception("连接服务器失败");

        var channel = connectState.CreateHttpChannel(); //创建管道连接器

        var result = false;

        try
        {
            await channel.SendAsync(_Encoder, request)
                .AsTask()
                .TimeoutAfter(request.Timeout);

            result = true;
        }
        finally
        {
            if (!result)
                await channel.CloseAsync(CloseReason.LocalClosing);
        }

        var packageStream = channel.GetPackageEnumerator();

        result = false;

        try
        {
            var response = await packageStream.ReceiveAsync()
                .AsTask()
                .TimeoutAfter(request.Timeout);

            result = true;

            return response;
        }
        finally
        {
            if (!result)
                await channel.CloseAsync(CloseReason.LocalClosing);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public enum HttpMethod
    {
        Get,
        Post,
    }
}